package com.yl.users.services.impl

import com.alibaba.fastjson.JSONObject
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper
import com.baomidou.mybatisplus.core.toolkit.Wrappers
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.yl.common.*
import com.yl.common.control.ResponseBody
import com.yl.common.control.returnError
import com.yl.common.control.returnSuccess
import com.yl.users.common.enum.TodoFlag
import com.yl.users.common.util.MD5Encoder
import com.yl.users.common.util.permissionsViewListToTree
import com.yl.users.entity.*
import com.yl.users.mapper.*
import com.yl.users.pojo.vo.CompanyPermissionsViewSelectVo
import com.yl.users.pojo.vo.CompanyUserSelectVo
import com.yl.users.services.ICompanyDeptService
import com.yl.users.services.ICompanyRoleService
import com.yl.users.services.ICompanyUserService
import com.yl.users.services.ISysCompanyService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.util.*
import java.util.concurrent.ConcurrentHashMap

@Service("iCompanyUserService")
open class CompanyUserServiceImpl(
	private val companyUserMapper: CompanyUserMapper,
	private val companyUserRoleMapper: CompanyUserRoleMapper,
	private val companyLinkDeptUserMapper: CompanyLinkDeptUserMapper,
	private val companyUserTodoMapper: CompanyUserTodoMapper,
	private val companyLinkSubCompanyDeptUserMapper: CompanyLinkSubCompanyDeptUserMapper

) : ICompanyUserService {

	private val map: ConcurrentHashMap<Long, SysCompany> = ConcurrentHashMap()

	@Autowired
	lateinit var iSysCompanyService: ISysCompanyService

	@Autowired
	lateinit var iCompanyDeptService: ICompanyDeptService

	@Autowired
	lateinit var iCompanyRoleService: ICompanyRoleService

	override fun getUser(id: Long): CompanyUser? {
		return getCacheUser(getContext().companyId,id)
	}


	override fun updateById(companyUser: CompanyUser): ResponseBody {

		val user = companyUserMapper.selectById(companyUser.id) ?: return returnError(
			ErrorCode.DATA_SAVE_FAILED,
			"未找到该用户，请刷新重试"
		)

		if (companyUser.realName.isNotEmpty()) {
			user.realName = companyUser.realName
		}
		if (companyUser.nickName != null) {
			user.nickName = companyUser.nickName
		}
		if (companyUser.phone != null) {
			user.phone = companyUser.phone
		}
		user.gender = companyUser.gender
		user.superUserId = companyUser.superUserId ?: 0L
		user.userWorkType = companyUser.userWorkType
		user.updateTime = Date()
		if (companyUserMapper.selectHaveSubId(
				user.id,
				user.superUserId!!,
				user.companyId
			) != 0
		) {
			return returnError(ErrorCode.OPERATION_DATA_ERROR, "该上级用户为你的下级")
		}
		if(companyUser.loginName != null && companyUser.loginName != ""){
			val selectCount = companyUserMapper.selectCount(
				QueryWrapper<CompanyUser?>().eq("login_name", companyUser.loginName).ne("id", companyUser.id)
			)
			if(selectCount != 0){
				return returnError(ErrorCode.OPERATION_DATA_ERROR, "存在相同的帐号")
			}
		}
		if(companyUser.loginName != null){
			user.loginName = companyUser.loginName
		}
		companyUserMapper.updateById(user)
		return returnSuccess()
	}

	override fun delUser(userId: Long): ResponseBody {
		companyUserMapper.update(null, Wrappers.update<CompanyUser?>().set("enabled", 0).eq("id", userId))
		return returnSuccess()
	}

	override fun getUserSubCompanyRoleIds(userId: Long, deptId: Long): List<Long> {
		return companyUserRoleMapper.getUserSubCompanyRoleIds(userId, deptId)
	}

	override fun getUserSubCompanyList(userId: Long): List<CompanyLinkSubCompanyDeptUser> {
		return companyLinkSubCompanyDeptUserMapper.selectList(Wrappers.query<CompanyLinkSubCompanyDeptUser?>().eq("user_id",userId))
	}

	override fun getUserSubCompanyRole(userId: Long, deptId: Long): List<CompanyRole> {
		return companyUserRoleMapper.getUserSubCompanyRole(userId, deptId)
	}

	override fun bindRoles(userId: Long, deptId: Long, roleIds: List<Long>): ResponseBody {
		iCompanyDeptService.bindUserToSubCompany(userId,deptId)
		companyUserRoleMapper.delete(
			Wrappers.query<CompanyLinkUserDeptRole>()
				.eq("user_id", userId)
				.eq("dept_id", deptId)
		)
		return addRoles(userId, roleIds, deptId)
	}

	override fun addRoles(userId: Long, roleIds: List<Long>, deptId: Long): ResponseBody {
		for (id in roleIds) {
			companyUserRoleMapper.insert(
				CompanyLinkUserDeptRole(
					roleId = id,
					userId = userId,
					deptId = deptId
				)
			)
		}
		return returnSuccess()
	}

	override fun unBindRoleBySubCompanyId(userId: Long, subCompanyId: Long): ResponseBody {
		companyUserRoleMapper.delete(
			Wrappers.query<CompanyLinkUserDeptRole?>().eq("dept_id",subCompanyId)
		)
		return returnSuccess()
	}

	override fun login(loginName: String, password: String): ResponseBody {
		val users =
			companyUserMapper.selectList(Wrappers.query<CompanyUser>().eq("login_name", loginName).eq("enabled", 1))
		if (users == null || users.size == 0) {
			return returnError(ErrorCode.LOGIN_ERROR, "账号密码错误")
		}
		if (users.size != 1) {
			return returnError(ErrorCode.LOGIN_ERROR, "账号异常，请联系管理员")
		}
		val loginUser = users[0]
		val uPass = MD5Encoder(password + loginUser.salt)
		if (uPass != loginUser.password) {
			return returnError(ErrorCode.LOGIN_ERROR, "账号密码错误")
		}
		var deptId = loginUser.lastLoginDeptId
		if (deptId == null) {
			val selectList =
				companyLinkDeptUserMapper.selectList(QueryWrapper<CompanyLinkDeptUser?>().eq("user_id", loginUser.id))
			if (selectList.isEmpty()) {
				return returnError(ErrorCode.LOGIN_ERROR, "用户未绑定部门，请联系管理员")
			}
			deptId = selectList[0].deptId
			companyUserMapper.update(
				null, Wrappers.update<CompanyUser?>()
					.eq("id", loginUser.id)
					.set("last_login_dept_id", deptId)
			)
		}


		val context = WebContext(
			userType = UserType.Company,
			companyId = loginUser.companyId,
			userId = loginUser.id,
			subCompanyId = deptId
		)

		setContext(context)
		return returnSuccess()
	}


	override fun updatePassword(userId: Long, oldPassword: String, newPassword: String): ResponseBody {
		val companyUser =
			companyUserMapper.selectById(userId) ?: return returnError(ErrorCode.DATA_IS_NOT_FIND, "未找到用户，请刷新重试")
		val uPass = MD5Encoder(oldPassword + companyUser.salt)
		if(uPass != companyUser.password){
			return returnError(ErrorCode.OPERATION_DATA_ERROR,"密码不正确")
		}
		return setPassword(companyUser,newPassword)
	}


	override fun setPassword(user: CompanyUser, newPassword: String): ResponseBody {
		user.randomSalt()
		user.password = MD5Encoder(newPassword + user.salt)
		companyUserMapper.updateById(user)
		return returnSuccess()
	}

	override fun getUserPermList(
		userId: Long,
		deptId: Long,
		vo: CompanyPermissionsViewSelectVo
	): MutableList<CompanyPermissionsView> {
		val perms = mutableListOf<CompanyPermissionsView>()
		val userPermIds = mutableSetOf<Long>()
		for (roleId in getUserSubCompanyRoleIds(userId, deptId)) {
			val permList = iCompanyRoleService.getRolePermList(roleId, vo)
			for (perm in permList) {
				if (!userPermIds.contains(perm.id)) {
					userPermIds.add(perm.id)
					perms.add(perm)
				}
			}
		}
		perms.sortBy { it.orderNum }
		return perms
	}

	override fun getUserMenuTree(userId: Long, deptId: Long): List<CompanyPermissionsView> {
		val user = getUser(userId)?: return listOf()
		val perms =
		if(user.userCode == "admin"){
			iSysCompanyService.getCompanyPermViewDirectoryMenuList(user.companyId)
		}else{
			getUserPermList(userId, deptId, CompanyPermissionsViewSelectVo(menuAndDirectory = true))
		}

		return permissionsViewListToTree(perms, 0L)
	}

//	override fun getUserButtonPerm(userId: Long, deptId: Long, menuId: Long): List<CompanyPermissionsDto> {
//		return companyUserMapper.selectUserButton(userId, deptId, menuId)
//	}

	override fun sendNoticeConfig(companyId: Long, userId: Long, name: String): JSONObject? {
		var company = this.map[companyId]
		if (company == null) {
			company = getCacheCompany(companyId) ?: return null
		}
		val userById = getCacheUser(companyId, userId) ?: return null
		val messageConfig = company.getMessageConfig(name) ?: return null
		when (name) {
			"SMS_BY_253" -> {
				messageConfig["mobilePhone"] = userById.phone
			}
			"WEBSOCKET" -> {
				messageConfig["userId"] = userById.id
			}
		}
		return messageConfig
	}

	override fun replaceCacheCompany(company: SysCompany) {
		val sysCompany = map[company.id]
		if (sysCompany != null) {
			for ((id, user) in sysCompany.users) {
				company.users[id] = user
			}
		}
		map[company.id] = company
	}

	override fun removeCacheUser(companyId: Long, userId: Long) {
		val company = map[companyId] ?: return
		val users = company.users
		users.remove(userId)
	}

	override fun getCacheCompany(companyId: Long): SysCompany? {
		val sysCompany = map[companyId]
		if (sysCompany == null) {
			map[companyId] = iSysCompanyService.getCompanyDetail(companyId) ?: return null
		}
		return map[companyId]
	}

	override fun getCacheUser(companyId: Long, userId: Long): CompanyUser? {
		try {
			var sysCompany = map[companyId]
			if (sysCompany == null) {
				sysCompany = iSysCompanyService.getCompanyDetail(companyId)

				if (sysCompany == null) {
					return null
				}
				map[sysCompany.id] = sysCompany
			}
			val userMap: ConcurrentHashMap<Long, CompanyUser> = sysCompany.users

			var companyUser = userMap[userId]
			if (companyUser == null) {
				companyUser = companyUserMapper.selectById(userId)
				if (companyUser == null) {
					return null
				}
				userMap[companyUser.id] = companyUser
			}
			return companyUser
		} catch (e: Exception) {
			return null
		}
	}

	override fun getCachePermissionsSet(companyId: Long, userId: Long, subCompanyId: Long): Set<String>? {
		val user = getCacheUser(companyId, userId) ?: return null

		var codes: HashSet<String>? = user.deptPerms[subCompanyId]
		if (codes == null || codes.isEmpty()) {
			val perms:List<CompanyPermissionsView> = if(user.userCode == "admin"){
				iSysCompanyService.getCompanyPermCodeList(getContext().companyId)
			}else{
				getUserPermList(userId, subCompanyId, CompanyPermissionsViewSelectVo())

			}


			codes = hashSetOf()
			for (code in perms) {
				if (!code.perms.isNullOrEmpty()) {
					codes.add(code.perms!!)
				}
			}
			user.deptPerms[subCompanyId] = codes
		}
		return codes
	}


	override fun havePermCode(companyId: Long, userId: Long, permCode: String, deptId: Long): Boolean {
		val set = getCachePermissionsSet(companyId, userId, deptId) ?: return false
		return set.contains(permCode)
	}


	override fun cleanCacheByCompany(companyId: Long) {
		val sysCompany = map[companyId] ?: return
		sysCompany.users.clear()
	}

	override fun switchSubCompany(subCompanyId: Long): ResponseBody {
//		if (companyLinkDeptUserMapper.selectCount(
//				QueryWrapper<CompanyLinkDeptUser?>().eq("userId", getContext()).eq("deptId", subCompanyId)
//			) == 0
//		) {
//			return returnError(ErrorCode.OPERATION_DATA_ERROR, "用户未绑定此部门")
//		}
		//待测试
		getContext().subCompanyId = subCompanyId
		companyUserMapper.update(
			null,
			UpdateWrapper<CompanyUser>().eq("id", getContext().userId).set("last_login_dept_id", subCompanyId)
		)
		removeCacheUser(getContext().companyId,getContext().userId)
		return returnSuccess()
	}

	override fun addTodo(companyUserTodo: CompanyUserTodo): ResponseBody {
		companyUserTodo.id = 0
		companyUserTodo.flag = TodoFlag.TO_BE_PROCESSED.code
		companyUserTodo.createTime = Date()

		if (companyUserTodo.planTime == null) {
			return returnError(ErrorCode.PARAM_EMPTY, "请输入计划时间")
		}
		companyUserTodoMapper.insert(companyUserTodo)
		return returnSuccess()
	}

	override fun page(page: Page<CompanyUserTodo>, companyUserTodo: CompanyUserTodo): Page<CompanyUserTodo> {
		return companyUserTodoMapper.selectPage(page, QueryWrapper(companyUserTodo).orderByDesc("plan_time"))
	}


	override fun getSubUserList(userId: Long, companyId: Long, vo: CompanyUserSelectVo): List<CompanyUser> {
		return companyUserMapper.getSubUserList(userId, companyId, vo)
	}

	override fun userIsInSubCompanyDept(subCompanyId: Long, userId: Long): Boolean {
		return companyLinkDeptUserMapper.subCompanyHaveUserInDept(userId,subCompanyId) != 0
	}
}

fun main() {
	println(MD5Encoder("hhkqtlw"+5279))
}
